package com.es.highLevel;

import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.elasticsearch.action.*;
import org.elasticsearch.action.search.SearchAction;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.*;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.threadpool.ThreadPool;

import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class SearchRequestTest {

    public static String HOSTNAME = "192.168.0.67";
    public static int PORT = 9200;
    public static String ES_USERNAME = "elastic";
    public static String ES_PASSWORD = "1BZTIs85w3fOovvdFodM";

    public static void main(String[] args) {

        RestHighLevelClient highLevelClient = getClient();
        ElasticsearchClient esClient = getEsClient(highLevelClient);
        SearchRequestBuilder requestBuilder = new SearchRequestBuilder(esClient, SearchAction.INSTANCE);
        requestBuilder.setIndices("product_info");
        requestBuilder.setFrom(0);
        requestBuilder.setSize(10);
        requestBuilder.setQuery(QueryBuilders.matchAllQuery());
        requestBuilder.addAggregation(AggregationBuilders.terms("productName").field("productName.keyword"));
        String s = requestBuilder.execute().actionGet().toString();
        System.out.println("检索结果：" + s);
        JSONObject jsonObject = JSONObject.parseObject(s);
        JSONObject aggregations = jsonObject.getJSONObject("aggregations");
        System.out.println("统计结果：" + aggregations);
        try {
            highLevelClient.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static ElasticsearchClient getEsClient(RestHighLevelClient highLevelClient){

        return new ElasticsearchClient() {
            @Override
            public <Request extends ActionRequest, Response extends ActionResponse> ActionFuture<Response> execute(ActionType<Response> action, Request request) {
                if (action.equals(SearchAction.INSTANCE) && request instanceof SearchRequest) {
                    return new ActionFuture<Response>() {
                        @Override
                        public Response actionGet() {
                            try {
                                return (Response) highLevelClient.search((SearchRequest) request, RequestOptions.DEFAULT);
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                            return null;
                        }

                        @Override
                        public Response actionGet(String timeout) {
                            try {
                                // 将字符串形式的时间转换为 TimeValue
                                TimeValue timeValue = TimeValue.parseTimeValue(timeout, "timeout");
                                SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
                                sourceBuilder.timeout(timeValue);
                                SearchRequest searchRequest = new SearchRequest();
                                searchRequest.source(sourceBuilder);
                                return (Response) highLevelClient.search((SearchRequest) request, RequestOptions.DEFAULT);
                            } catch (IOException e) {
                                throw new RuntimeException(e);
                            }
                        }

                        @Override
                        public Response actionGet(long timeoutMillis) {
                            try {
                                SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
                                sourceBuilder.timeout(TimeValue.timeValueMillis(timeoutMillis));
                                SearchRequest searchRequest = new SearchRequest();
                                searchRequest.source(sourceBuilder);
                                return (Response) highLevelClient.search((SearchRequest) request, RequestOptions.DEFAULT);
                            } catch (IOException e) {
                                throw new RuntimeException(e);
                            }
                        }

                        @Override
                        public Response actionGet(long timeout, TimeUnit unit) {
                            return null;
                        }

                        @Override
                        public Response actionGet(TimeValue timeout) {
                            return null;
                        }

                        @Override
                        public boolean cancel(boolean mayInterruptIfRunning) {
                            return false;
                        }

                        @Override
                        public boolean isCancelled() {
                            return false;
                        }

                        @Override
                        public boolean isDone() {
                            return false;
                        }

                        @Override
                        public Response get() throws InterruptedException, ExecutionException {
                            return null;
                        }

                        @Override
                        public Response get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
                            return null;
                        }
                    };
                } else {
                    throw new UnsupportedOperationException("Unsupported action: " + action.name());
                }
            }

            @Override
            public <Request extends ActionRequest, Response extends ActionResponse> void execute(ActionType<Response> action, Request request, ActionListener<Response> listener) {
                if (action.equals(SearchAction.INSTANCE) && request instanceof SearchRequest) {
                    highLevelClient.searchAsync((SearchRequest) request, RequestOptions.DEFAULT, (ActionListener<SearchResponse>) listener);
                } else {
                    throw new UnsupportedOperationException("Unsupported action: " + action.name());
                }
            }

            @Override
            public ThreadPool threadPool() {
                return null;
            }
        };
    }

    /**
     * 初始化客户端
     * @return RestHighLevelClient
     */
    private static RestHighLevelClient getClient(){
        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(ES_USERNAME, ES_PASSWORD));
        RestClientBuilder restClientBuilder = RestClient.builder(new HttpHost(HOSTNAME, PORT))
                .setHttpClientConfigCallback(httpAsyncClientBuilder -> httpAsyncClientBuilder.setDefaultCredentialsProvider(credentialsProvider));
        RestHighLevelClient highLevelClient = new RestHighLevelClient(restClientBuilder);
        return highLevelClient;
    }

}
